# -*- coding: utf-8 -*-
import xlsxwriter as xw
import os
import json
import argparse
import sys
import logging
import time

'''
1. Look for result.json
2. search testcase name and step name
3. split step to request and response
4. write to excel
'''

class Testcase():
    def __init__(self, path):
        self.path = path
        # 初始化日志
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            filename=os.path.join(path, 'testcase.log')
        )
        self.logger = logging.getLogger(__name__)
    
    def get_result_file(self):
        try:
            files = os.listdir(self.path)
            result_files = [file for file in files if 'result' in file]
            self.result_files = result_files
            return self.result_files
        except Exception as e:
            self.logger.error(f"获取结果文件失败: {str(e)}")
            raise

    def get_testcase(self):
        testcases = []
        for result_file in self.result_files:
            try:
                file_path = os.path.join(self.path, result_file)
                with open(file_path, 'r', encoding='utf8') as f:
                    json_data = json.load(f)
                    testcase = self._parse_testcase(json_data)
                    testcases.append(testcase)
            except Exception as e:
                self.logger.warning(f"解析测试用例 {result_file} 失败: {str(e)}")
                continue
        self.testcases = testcases
        return self.testcases

    def _parse_testcase(self, json_data):
        """解析单个测试用例数据"""
        testcase = {
            'Name': self._get_testcase_name(json_data),
            'status': json_data.get('status', 'Na'),
            'Request': [],
            'Response': []
        }
        
        for i, step in enumerate(json_data.get('steps', []), start=1):
            step_name = step.get('name', 'No Step')
            request, response = self._parse_step(step_name, i)
            testcase['Request'].append(request)
            testcase['Response'].append(response)
        time.sleep(0.005)    
        return testcase

    def _get_testcase_name(self, json_data):
        """获取测试用例名称"""
        name = str(json_data.get('name', ''))
        if isinstance(json_data.get('parameters'), list) and json_data['parameters']:
            param_value = str(json_data['parameters'][0].get('value', '')).replace("'", "").replace(" ", "")
            name = f"{name} : {param_value}"
        return name

    def _parse_step(self, step_name, step_num):
        """解析单个步骤"""
        parts = step_name.split('#')
        request = f"{step_num}.{parts[0].strip()}"
        response = f"{step_num}.{parts[1].strip()}" if len(parts) > 1 else f"{step_num}.NA"
        return request, response

    def get_data(self, Function_Mode='', Numb='', Maintainers='', type='', level='P2', 
                link='', method='', env='', Precondition='', Focus='', Comment='', status=''):
        excel_datas = []       
        for testcase in self.testcases:
            excel_data = {"Function_Mode": '', "Numb": "", "Title": '', 'status': '',
                        'Maintainers':'','Type':'','level':'',
                        'link':'','Method':'','Env':'','Precondition':'','Description':'',
                        'Expected':'NA','Focus':'','Comment':''}
            excel_data['Function_Mode'] = Function_Mode
            excel_data['Numb'] = Numb
            excel_data['Maintainers'] = Maintainers
            excel_data['Type'] = type
            excel_data['level'] = level
            excel_data['link'] = link
            excel_data['Method'] = method
            excel_data['Env'] = env
            excel_data['Precondition'] = Precondition
            excel_data['Focus'] = Focus
            excel_data['Comment'] = Comment
            excel_data['Title'] = testcase['Name']
            if testcase['status'] == 'passed':
                excel_data['status'] = 'Pass'
            elif testcase['status'] == 'failed':
                excel_data['status'] = 'Fail'
            else:
                excel_data['status'] = 'Na'
            str_request=''
            str_response=''
            for i,request in enumerate(testcase['Request']):
                if i == 0:
                    str_request = request
                else:
                    str_request = str_request+'\n'+request
            for i,response in enumerate(testcase['Response']):
                if i == 0:
                    str_response = response
                else:
                    str_response = str_response+'\n'+response
            excel_data['Description'] = str_request
            excel_data['Expected'] = str_response
            excel_datas.append(excel_data)
        self.excel_datas = excel_datas
        return self.excel_datas

    def write_excel(self, filepath):
        try:
            # 确保输出目录存在
            os.makedirs(filepath, exist_ok=True)
            
            # 修正文件名生成逻辑
            if hasattr(self, 'output_file_name'):  # 如果有自定义文件名
                fileName = os.path.join(filepath, f"{self.output_file_name}.xlsx")
            else:
                fileName = os.path.join(filepath, "TestReport.xlsx")  # 默认文件名
            
            with xw.Workbook(fileName) as workbook:
                worksheet1 = workbook.add_worksheet("sheet1")
                
                # 设置自动换行格式
                wrap_format = workbook.add_format({'text_wrap': True})
                
                # 批量写入标题
                title = ['功能模块', '编号', '*标题','测试结果','维护人', '用例类型', '重要程度',
                        '测试用例设计方法','测试方法类型','测试环境', '前置条件', '步骤描述',
                        '预期结果','测试结果', '关注人', '备注']
                worksheet1.write_row('A2', title)
                
                # 设置列宽
                worksheet1.set_column('A:A', 15)  # 功能模块
                worksheet1.set_column('B:B', 10)  # 编号
                worksheet1.set_column('C:C', 30)  # 标题
                worksheet1.set_column('D:D', 10)  # 测试结果
                worksheet1.set_column('E:E', 15)  # 维护人
                worksheet1.set_column('F:F', 15)  # 用例类型
                worksheet1.set_column('G:G', 10)  # 重要程度
                worksheet1.set_column('H:H', 20)  # 测试用例设计方法
                worksheet1.set_column('I:I', 15)  # 测试方法类型
                worksheet1.set_column('J:J', 15)  # 测试环境
                worksheet1.set_column('K:K', 20)  # 前置条件
                worksheet1.set_column('L:L', 40)  # 步骤描述
                worksheet1.set_column('M:M', 40)  # 预期结果
                worksheet1.set_column('N:N', 10)  # 测试结果
                worksheet1.set_column('O:O', 15)  # 关注人
                worksheet1.set_column('P:P', 20)  # 备注
                
                # 批量写入数据
                for i, data in enumerate(self.excel_datas, start=3):
                    row_data = [
                        data["Function_Mode"], data["Numb"], data["Title"],
                        data["status"], data["Maintainers"], data["Type"],
                        data["level"], data["link"], data["Method"],
                        data["Env"], data["Precondition"], data["Description"],
                        data["Expected"], data["Focus"], data["Comment"]
                    ]
                    worksheet1.write_row(f'A{i}', row_data, wrap_format)
                    
                    # 自动调整行高
                    worksheet1.set_row(i-1, None, None, {'hidden': False, 'level': 0, 'collapsed': False})
                    
        except Exception as e:
            self.logger.error(f"写入Excel失败: {str(e)}")
            raise

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='生成测试用例Excel报告')
    # 修改path参数为可选，默认使用当前目录
    parser.add_argument('--path', help="Allure结果文件夹路径", type=str, default=os.getcwd() + "\\allure-results")
    parser.add_argument('--output', help="生成的Excel文件名(不含扩展名)", type=str, default="")
    
    # 保留原有其他参数
    parser.add_argument("--module", help="功能模块", type=str, default="")
    parser.add_argument("--Numb", help="this is parameter to select 编号", type=str, default="")
    parser.add_argument("--Maintainers", help="this is parameter to select 维护人", type=str, default="杨亮") 
    parser.add_argument("--Type", help="this is parameter to select testcase 用例类型", type=str, default="功能测试") 
    parser.add_argument("--level", help="this is parameter to select 重要程度", type=str, default="High") 
    parser.add_argument("--link", help="this is parameter to select 测试用例设计方法", type=str, default="基于需求的设计方法")
    parser.add_argument("--Method", help="this is parameter to select 测试方法类型", type=str, default="诊断测试")
    parser.add_argument("--Env", help="this is parameter to select 测试环境", type=str, default="自动化测试平台") 	
    parser.add_argument("--Precondition", help="this is parameter to select 前置条件", type=str, default="") 
    parser.add_argument("--Focus", help="this is parameter to select 关注人", type=str, default="")             
    parser.add_argument("--Comment", help="this is parameter to select 备注", type=str, default="") 
    args = parser.parse_args()
    time.sleep(0.1)
    path = args.path

    if os.path.exists(path):
        tc = Testcase(path)
        if args.output:
            tc.output_file_name = args.output  # 存储自定义文件名
        result_file = tc.get_result_file()
        all_testcases = tc.get_testcase()
        all_datas = tc.get_data(args.module, args.Numb, args.Maintainers, args.Type, 
                              args.level, args.link, args.Method, args.Env, 
                              args.Precondition, args.Focus, args.Comment)
        
        # 修改输出路径为脚本所在目录
        script_dir = os.path.dirname(os.path.abspath(__file__))
        folder_name = os.path.basename(script_dir)
        
        # 确定输出文件名
        if args.output:
            output_file = os.path.join(script_dir, f"{args.output}")
        else:
            output_file = os.path.join(script_dir, f"{folder_name}")
            
        tc.write_excel(output_file)
        print(f"测试报告已生成: {output_file}")
    else:
        print(f'路径错误! 指定的路径不存在: {path}')